import { PNode } from "~/models/graph/node/prototype";
import { PNodeType } from "~/models/graph/node/type";
import { PSlot } from "~/models/graph/slot/prototype";
import { PyBundle } from "./PyBundle";
import { tBool, tNull, tNum, tStr } from "~/models/types";
import { typeFromJs as _t } from "~/models/types/utils";
import { InterfaceType } from "~/models/types/interface_type";
import { ChoiceType } from "~/models/types/choice_type";
import { UnionType } from "~/models/types/union_type";
import { PyFunc, PyFuncSign } from "../pyCode/PyFunc";
import { PyPkg } from "../pyCode/PyPkg";
import { PSlotType } from "../graph/slot/type";

/**
 * 按键精灵模组
 */
const bundle = new PyBundle('keymouse', '按键精灵');

/** 平面点类型 */
export const tPoint = _t({ __meta: 'Point', x: Number, y: Number })

/** 平面尺寸类型 */
export const tSize = _t({ __meta: 'Size', width: Number, height: Number })

/** 鼠标位置详细类型 */
export const tMousePosition = _t({
  __meta: 'MousePosition',
  windowname: String,
  windowposition: tPoint,
  windowsize: tSize,
  screensize: tSize,
  globalposition: tPoint,
})

/** 鼠标按钮类型 */
export const tMouseButton = new ChoiceType('MouseButton', [
  'None',
  'Left',
  'Middle',
  'Right',
])

/** 鼠标动作类型 */
export const tMouseAction = new ChoiceType('MouseAction', [
  'None',
  'Click',
  'Press',
  'Release',
])

/** 鼠标记录类型 */
export const tMouseRecord = _t({
  __meta: 'MouseRecord',
  position: tMousePosition,
  button: tMouseButton,
  action: tMouseAction
})

/** 色彩类型 */
export const tColor = _t({
  __meta: 'Color',
  r: Number,
  g: Number,
  b: Number
})

/** 键类型 */
export const tKey = _t({ __meta: 'Key', key: String, code: String })

/** 按键动作类型 */
export const tKeyAction = new ChoiceType('KeyAction', [
  'None',
  'Down',
  'Press',
  'Up',
])

/** 按键记录类型 */
export const tKeyRecord = _t({ __meta: 'KeyRecord', key: tKey, action: tKeyAction })

bundle.typeDeclares = [
  // tMousePosition,
  tColor,
  // tMouseButton,
  // tMouseAction,
  tMouseRecord,
  tKeyRecord,
]

bundle.addFunc(new PyFunc({
  sign: new PyFuncSign('等待', [
    { name: '秒', type: tNum  }
  ]),
  implement:`\
def 等待(秒):
  time.sleep(秒)
  `,
  dependencies:[
    new PyPkg('time')
  ]
}))

const funcTranslate = new PyFunc({
  sign: new PyFuncSign('translate'),
  implement:`\
def translate(pos):
  windowname = pos['windowname']
  screensize = pos['screensize']
  globalposition = pos['globalposition']
  windowposition = pos['windowposition']
  windowsize = pos['windowsize']

  hwnd = win32gui.FindWindow(None, windowname)
  if not hwnd:
    raise Exception(f"未找到标题为'{windowname}'的窗口。")
  # 计算当时的局部坐标
  local_x = (globalposition['x'] - windowposition['x']) / windowsize['width']
  local_y = (globalposition['y'] - windowposition['y']) / windowsize['height']
  # 计算新的全局坐标
  wl, wt, wr, wb = win32gui.GetWindowRect(hwnd)
  ww = wr - wl
  wh = wb - wt
  global_x = int(wl + ww * local_x)
  global_y = int(wt + wh * local_y)
  return global_x, global_y
  `,
  dependencies:[
    new PyPkg('win32gui')
  ]
})

const funcEnsureFg = new PyFunc({
  sign: new PyFuncSign('ensure_fg'),
  implement:`\
def ensure_fg(pos):
  windowname = pos['windowname']
  hwnd = win32gui.FindWindow(None, windowname)
  if not hwnd:
    raise Exception(f"未找到标题为'{windowname}'的窗口。")
  foreground_hwnd = win32gui.GetForegroundWindow()  # 获取前台窗口句柄
  if foreground_hwnd != hwnd:
    win32gui.SendMessage(hwnd, win32con.WM_SYSCOMMAND, win32con.SC_RESTORE, 0)
    pyautogui.press("alt")
    win32gui.SetForegroundWindow(hwnd)
  `,
  dependencies:[
    new PyPkg('win32gui'),
    new PyPkg('pyautogui'),
    new PyPkg('win32con'),
  ]
})

bundle.beforeFun += `\
pyautogui.PAUSE = 0.05
`

bundle.addFunc(new PyFunc({
  sign: new PyFuncSign('鼠标操作', [
    { name: '位置', type: tMousePosition  },
    { name: '按键', type: tMouseButton, defaultValue: literal('Left')  },
    { name: '动作', type: tMouseAction, defaultValue: literal('Click')  },
    { name: '次', type: tNum, defaultValue: literal(1)  },
  ]),
  implement:`\
def 鼠标操作(position, button, action, times):
  p = translate(position)
  ensure_fg(position)
  pyautogui.moveTo(p[0], p[1])
  for i in range(times):
    if button == 'Left':
      if action == 'Click':
        pyautogui.leftClick()
      elif action == 'Press':
        pyautogui.mouseDown(button='left')
      elif action == 'Release':
        pyautogui.mouseUp(button='left')
    elif button == 'Middle':
      if action == 'Click':
        pyautogui.middleClick()
      elif action == 'Press':
        pyautogui.mouseDown(button='middle')
      elif action == 'Release':
        pyautogui.mouseUp(button='middle')
    elif button == 'Right':
      if action == 'Click':
        pyautogui.rightClick()
      elif action == 'Press':
        pyautogui.mouseDown(button='right')
      elif action == 'Release':
        pyautogui.mouseUp(button='right')
  `,
  dependencies:[
    funcTranslate,
    funcEnsureFg,
    new PyPkg('pyautogui')
  ]
}))


bundle.addFunc(new PyFunc({
  sign: new PyFuncSign('拖拽', [
    { name: '起点', type: tMousePosition },
    { name: '终点', type: tMousePosition },
  ]),
  implement:`\
def 拖拽(point1, point2):
  p1 = translate(point1)
  p2 = translate(point2)
  ensure_fg(point1)
  pyautogui.moveTo(p1[0], p1[1])
  pyautogui.mouseDown()
  time.sleep(0.1)
  t = pyautogui.PAUSE
  pyautogui.PAUSE /= 10
  # 补间移动
  for i in range(20):
    b = (i+1.0) / 20.0
    a = 1 - b
    _x = p1[0] * a + p2[0] * b
    _y = p1[1] * a + p2[1] * b
    pyautogui.moveTo(_x, _y)

  pyautogui.PAUSE = t
  time.sleep(0.1)
  pyautogui.mouseUp()
  `,
  dependencies:[
    funcTranslate,
    funcEnsureFg,
    new PyPkg('pyautogui'),
    new PyPkg('time')
  ]
}))

bundle.addFunc(new PyFunc({
  sign: new PyFuncSign('检查颜色', [
    { name: '采样点', type: tMousePosition },
    { name: '颜色', type: tColor },
    { name: '容差', type: tNum },
  ],[
    { name: '一致', type: tBool },
  ]),
  implement:`\
def 检查颜色(point, color, threshold):
  p = translate(point['x'], point['y'])
  pyautogui.moveTo(p[0], p[1])
  c = pyautogui.pixel(p[0], p[1])
  c1 = [color['r'], color['g'], color['b']]
  delta = [
    abs((c[0] - c1[0]) / c1[0]),
    abs((c[1] - c1[1]) / c1[1]),
    abs((c[2] - c1[2]) / c1[2])
  ]
  delta_rate = sum(delta)/3
  print(f'捕捉点: {p}')
  print(f'捕捉颜色: {c}')
  print(f'原有颜色: {c1}')
  print(f'delta: {delta}')
  print(f'delta_rate: {delta_rate}')
  return delta_rate < threshold
  `,
  dependencies:[
    funcTranslate,
    funcEnsureFg,
    new PyPkg('pyautogui'),
    new PyPkg('time')
  ]
}))

bundle.extraNode = [
  new PNode({
    type: PNodeType.Process,
    name: 'Repeat',
    title: '重复',
    slots: [
      PSlot.Preset.ProcessIn,
      PSlot.Preset.ProcessOut,
      PSlot.InData('times', '次数', tNum),
      new PSlot('_out_inner', '重复', 'out', PSlotType.Process),
    ],
    processTemplate: "for i in range(%(data[0])s):\n",
    branchTemplate: "%(process[0])s\n",
  }),
]

export const bunKeyMouse = bundle